package org.fly.service.impl;

import org.fly.bean.*;
import org.fly.bean.query.CustomerLevelQuery;
import org.fly.bean.query.OrderQuery;
import org.fly.bean.query.SCLRQuery;
import org.fly.bean.query.SupplierProductQuery;
import org.fly.bean.warpper.OrderProductWarpper;
import org.fly.bean.warpper.OrderWarpper;
import org.fly.contants.ErrorConstant;
import org.fly.contants.WebConstant;
import org.fly.dao.*;
import org.fly.enums.OrderStatus;
import org.fly.enums.SmsType;
import org.fly.service.OrderService;
import org.fly.service.SmsRecordService;
import org.fly.service.SupplierProductService;
import org.fly.utils.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.fly.bean.common.BusinessException;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* Created by autoCode on 2018-04-10 19:13:41.
*/
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    OrderDao orderDao;
    @Autowired
    ProductDao productDao;
    @Autowired
    ProductNormDao productNormDao;
    @Autowired
    SupplierProductDao supplierProductDao;
    @Autowired
    SupplierProductService supplierProductService;
    @Autowired
    CustomerLevelDao customerLevelDao;
    @Autowired
    SCLRDao sclrDao;
    @Autowired
    CustomerDao customerDao;
    @Autowired
    SupplierDao supplierDao;
    @Autowired
    OrderProductDao orderProductDao;
    @Autowired
    CartDao cartDao;
    @Autowired
    SmsTemplateDao smsTemplateDao;
    @Autowired
    SmsRecordService smsRecordService;

    @Override
    public List<Order> list(OrderQuery query) {
        return orderDao.list(query);
    }

    @Override
    public long count(OrderQuery query) {
        return orderDao.count(query);
    }

    @Override
    public List<OrderWarpper> listWarpper(OrderQuery query) {
        List<Order>  orders =  orderDao.list(query);
        List<String> orderIdList  = new ArrayList<>();
        List<String> supplierIdList = new ArrayList<>();
        List<String> customerIdList = new ArrayList<>();
        orders.forEach(e->{
            if(!orderIdList.contains(e.getId())){
                orderIdList.add(e.getId());
            }
            if(!supplierIdList.contains(e.getSupplierId())){
                supplierIdList.add(e.getSupplierId());
            }
            if(!customerIdList.contains(e.getCustomerId())){
                customerIdList.add(e.getCustomerId());
            }
        });
        List<Supplier> suppliers = supplierDao.listByIds(supplierIdList);
        List<Customer> customers = customerDao.listByIds(customerIdList);
        List<OrderProduct> orderProducts = orderProductDao.listByOrderIdList(orderIdList);
        List<String> productIdList = orderProducts.stream().map(e->e.getProductId()).collect(Collectors.toList());

        List<Product> products = productDao.listByIds(productIdList);
        Map<String,Product> productMap = products.stream().collect(Collectors.toMap(e->e.getId(),e->e));
        Map<String,Supplier> supplierMap =  suppliers.stream().collect(Collectors.toMap(e->e.getId(),e->e));
        Map<String,Customer> customerMap = customers.stream().collect(Collectors.toMap(e->e.getId(),e->e));

        List<OrderProductWarpper >  orderProductWarppers = orderProducts.stream().map(e->{
            OrderProductWarpper warpper = new OrderProductWarpper();
            BeanUtils.copyProperties(e,warpper);
            Product product =  productMap.get(e.getProductId());
            warpper.setProduct(product);
            return warpper;
        }).collect(Collectors.toList());

        Map<String,List<OrderProductWarpper>> opMap = orderProductWarppers.stream().
                collect(Collectors.groupingBy(e->e.getOrderId(),Collectors.toList()));
        return orders.stream().map(e->{
            OrderWarpper warpper = new OrderWarpper();
            BeanUtils.copyProperties(e,warpper);
            List<OrderProductWarpper> _orderProductWarppers= opMap.get(e.getId());
            warpper.setOrderProducts(_orderProductWarppers);
            Supplier supplier =  supplierMap.get(e.getSupplierId());
            warpper.setSupplier(supplier);
            Customer customer = customerMap.get(e.getCustomerId());
            warpper.setCustomer(customer);

            return warpper;
        }).collect(Collectors.toList());
    }

    @Override
    public void updateOrderStatus(String orderId, String status) throws BusinessException {
        Order order = orderDao.findById(orderId);
        OrderStatus statusEnum = null;
        try{
             statusEnum =  OrderStatus.valueOf(status);
        }catch (Exception e){
            throw new BusinessException(ErrorConstant.ec_enum_error,ErrorConstant.em_enum_error_order_status);
        }
        order.setStatus(status);
        //发送短信
        sendSmsForOrderStatusChange(order,statusEnum);
        orderDao.update(order);
    }

    @Override
    public Order findById(String id) {
        return orderDao.findById(id);
    }

    @Override
    public void save(Order bean)  throws BusinessException {

    if(StringUtils.isNotBlank(bean.getId())){
         orderDao.update(bean);
    }else {
        bean.setOrderNo(StringUtil.createBusinessNo());
        bean.setId(UUIDFactory.random());
        bean.setCreateTime(System.currentTimeMillis());
        orderDao.insert(bean);
    }
    }

    @Override
    public void delete(String id) {
        orderDao.delete(id);
    }

    @Transactional
    @Override
    public void createByProduct(OrderProduct orderProduct,String customerId) throws BusinessException {

        if(StringUtils.isBlank(orderProduct.getProductId())){
            throw new BusinessException(ErrorConstant.ec_param_error, ErrorConstant.em_param_no_product_id);
        }
        if(StringUtils.isBlank(orderProduct.getSupplierId())){
            throw new BusinessException(ErrorConstant.ec_param_error, ErrorConstant.em_param_no_supplier_id);
        }
        if(orderProduct.getNum()<=0){
            throw new BusinessException(ErrorConstant.ec_param_error, ErrorConstant.em_param_error_num);
        }
        Order order = new Order();
        order.setOrderNo(StringUtil.createBusinessNo());
        order.setId(UUIDFactory.random());
        ProductNorm  productNorm = productNormDao.findByProductId(orderProduct.getProductId());
        if(productNorm !=null  ){
            String normValue =  productNorm.getValues();
            if(StringUtils.isBlank(orderProduct.getNorm()) ||
                    normValue.indexOf(orderProduct.getNorm()) <0   ){
                throw new BusinessException(ErrorConstant.ec_param_error, ErrorConstant.em_param_error_norm);
            }
        }

        SupplierProduct supplierProduct=  supplierProductService.find(orderProduct.getSupplierId(),
                orderProduct.getProductId());

        orderProduct.setCreateTime(System.currentTimeMillis());
        orderProduct.setId(UUIDFactory.random());
        Product product = productDao.findById(orderProduct.getProductId());
        orderProduct.setProductJson(JsonUtils.encode(product));
        String customerLevel =  getCustomerLevel(customerId,orderProduct.getSupplierId());

        String singlePrice = PriceUtils.calcPrice(supplierProduct,customerLevel,
                productNorm,orderProduct.getNorm()
               );
        orderProduct.setPrice(singlePrice);
        String  money = StringNumber.mul(singlePrice,String.valueOf(orderProduct.getNum()));
        orderProduct.setMoney(money);
        orderProduct.setPriceJson(supplierProduct.getConfigJson());
        orderProduct.setOrderId(order.getId());

        order.setStatus(OrderStatus.create.name());
        order.setTotalMoney(orderProduct.getMoney());
        order.setCreateTime(System.currentTimeMillis());
        fillCustomer(order,customerId);
        fillSupplier(order,orderProduct.getSupplierId());
        orderDao.insert(order);
        orderProductDao.insert(orderProduct);
        sendSmsForOrderStatusChange(order,OrderStatus.create);
    }

    @Transactional
    @Override
    public void createByCart(List<String> cartIdList, String customerId) throws BusinessException {
        List<Cart>  carts =  cartDao.listByIds(cartIdList);
        //供货商必须一致
        String  supplierId =  carts.get(0).getSupplierId();
        List<String> productIdList = new ArrayList<>();
        for(int i=0; i< carts.size();i++){
            Cart cart =  carts.get(i);
            if(!cart.getSupplierId().equals(supplierId)){
                throw new BusinessException(ErrorConstant.ec_business_error,
                        ErrorConstant.em_business_cart_supplier_error);
            }
            if(!productIdList.contains(cart.getProductId())){
                productIdList.add(cart.getProductId());
            }
        }

        //计算客户级别
        String customerLevel =  getCustomerLevel(customerId,supplierId);
        //获取商品信息
        List<Product> products =  productDao.listByIds(productIdList);
        Map<String,Product> productMap = products.stream().collect(Collectors.toMap(e->e.getId(),e->e));
        //获取供货商商品报价
        SupplierProductQuery spQuery = new SupplierProductQuery();
        spQuery.setProductIdList(productIdList);
        spQuery.setSupplierId(supplierId);
        List<SupplierProduct> supplierProducts = supplierProductDao.list(spQuery);
        Map<String,SupplierProduct> spMap = supplierProducts.stream().
                collect(Collectors.toMap(e->e.getProductId(),e->e));
        //获取商品规格信息
        List<ProductNorm> productNormList = productNormDao.listByProductIds(productIdList);
        Map<String,ProductNorm> pnMap  = productNormList.stream().collect(Collectors.toMap(e->e.getProductId(),e->e));
        //构建商品订单
        List<OrderProduct> orderProducts = new ArrayList<>();
        long now  = System.currentTimeMillis();
        Order order = new Order();
        order.setId(UUIDFactory.random());
        order.setOrderNo(StringUtil.createBusinessNo());
        order.setTotalMoney("0");
        carts.stream().forEach(e->{
            OrderProduct  orderProduct = new OrderProduct();
            orderProduct.setId(UUIDFactory.random());
            orderProduct.setNorm(e.getNorm());
            orderProduct.setNum(e.getNum());
            orderProduct.setSupplierId(e.getSupplierId());
            orderProduct.setProductId(e.getProductId());
            orderProduct.setOrderId(order.getId());
            Product product = productMap.get(e.getProductId());
            orderProduct.setProductJson(JsonUtils.encode(product));
            SupplierProduct supplierProduct = spMap.get(e.getProductId());
            orderProduct.setPriceJson(supplierProduct.getConfigJson());
            ProductNorm productNorm = pnMap.get(e.getProductId());
            String singlePrice = PriceUtils.calcPrice(supplierProduct,customerLevel,
                    productNorm,orderProduct.getNorm()
                    );

            String  money = StringNumber.mul(singlePrice,String.valueOf(orderProduct.getNum()));
            orderProduct.setPrice(singlePrice);
            orderProduct.setMoney(money);
            orderProduct.setCreateTime(now);
            order.setTotalMoney(StringNumber.add(order.getTotalMoney(),money));
            orderProducts.add(orderProduct);
        });
        order.setStatus(OrderStatus.create.name());
        order.setCreateTime(System.currentTimeMillis());
        fillCustomer(order,customerId);
        fillSupplier(order,supplierId);
        orderDao.insert(order);
        orderProductDao.batchInsert(orderProducts);
        cartDao.deleteByIdList(cartIdList);
        sendSmsForOrderStatusChange(order,OrderStatus.create);
    }

    /**
     * 填充客户信息
     * @param order
     * @param customerId
     */
    private void fillCustomer(Order order ,String customerId) throws BusinessException{
        Customer customer =  customerDao.findById(customerId);
        if(StringUtils.isBlank(customer.getAddress())){
            throw new BusinessException(ErrorConstant.ec_param_error,
                    ErrorConstant.ec_param_customer_address_null);
        }
        if(StringUtils.isBlank(customer.getTelephone())){
            throw new BusinessException(ErrorConstant.ec_param_error,
                    ErrorConstant.ec_param_customer_telephone_null);
        }
        order.setAddress(customer.getAddress());
        order.setcTelephone(customer.getTelephone());
        order.setCustomerId(customerId);
        order.setcName(customer.getName());
    }

    private void fillSupplier(Order order,String supplierId){
        Supplier  supplier = supplierDao.findById(supplierId);
        order.setSupplierId(supplierId);
        order.setsName(supplier.getShopName());
        order.setsTelephone(supplier.getTelephone());

    }





    /**
     * 计算 客户的 级别
     * @param customerId
     * @param supplierId
     * @return
     */
    private String getCustomerLevel(String customerId, String supplierId){
        CustomerLevelQuery customerLevelQuery = new CustomerLevelQuery();
        customerLevelQuery.setSupplierId(supplierId);
        List<CustomerLevel> customerLevels = customerLevelDao.list(customerLevelQuery);
        //供货商默认的级别map
        Map<String,CustomerLevel> customerLevelMap = customerLevels.stream().filter(e->e.getDefaultSet()  ==1 ).
                collect(Collectors.toMap(e->e.getSupplierId(), e->e));

        SCLRQuery sclrQuery = new SCLRQuery();
        sclrQuery.setSupplierId(supplierId);
        sclrQuery.setCustomerId(customerId);
        List<SCLR>  sclrs  = sclrDao.list(sclrQuery);
        Map<String,SCLR> sclrMap = sclrs.stream().collect(Collectors.toMap(e->e.getSupplierId(),e->e));
       return CustomerLevelUtils.getCustomerLevel(customerId,supplierId,customerLevelMap,sclrMap);
    }

    private SmsType getByOrderStatus(OrderStatus orderStatus){
        SmsType  smsType = null;
        switch (orderStatus){
            case create:smsType = SmsType.createOrder;break;
            case confirm:smsType = SmsType.confirm;break;
            case dispatch:smsType = SmsType.delivery;break;
            case finish:smsType =SmsType.finishOrder;break;
        }
        return smsType;
    }

    /**
     * 订单状态改变告知 下单者
     * @param order
     * @param orderStatus
     */
    private void sendSmsForOrderStatusChange(Order order,OrderStatus orderStatus){
        try{
            SmsType smsType = getByOrderStatus(orderStatus);
            SmsTemplate smsTemplate = smsTemplateDao.findByType(smsType.name());
            Map<String,Object> param = new HashMap<>();
            param.put("cName",order.getcName());
            param.put("sName",order.getsName());
            param.put("orderStatus",orderStatus.getName());
            param.put("orderNo",order.getOrderNo());
            String telephone = null;
            if(OrderStatus.create == orderStatus){
                telephone = order.getsTelephone();
            }else {
                telephone = order.getcTelephone();
            }
            if(smsTemplate !=null){

                smsRecordService.sendSms(telephone,smsType,smsTemplate.getAliTemplateCode(),param);
            }
        }catch (Exception e){

        }

    }



}
